package com.zlsy.secondtime.deadlock;

import java.util.concurrent.TimeUnit;

/**
 * @author zhouliang
 * @date 2020/6/18 21:20
 * 换序来解决死锁的问题
 */
public class ChangingOrderToSolveDeadlock implements Runnable {

    int flag = 1;
    private static final ChangingOrderAccount a = new ChangingOrderAccount(500);
    private static final ChangingOrderAccount b = new ChangingOrderAccount(500);
    private static final Object LOCK = new Object();

    @Override
    public void run() {
        if (flag == 1) {
            transferMoney(a, b, 200);
        }
        if (flag == 0) {
            transferMoney(b, a, 200);
        }
    }

    private void transferMoney(ChangingOrderAccount from, ChangingOrderAccount to, int amount) {

        int fromHashCode = System.identityHashCode(from);
        int toHashCode = System.identityHashCode(to);
        if (fromHashCode < toHashCode) {
            synchronized (from) {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (to) {
                    if (from.balance - amount < 0) {
                        System.err.println("余额不足！");
                    }
                    from.balance -= amount;
                    to.balance += amount;
                    System.out.println("转账完成！");
                }
            }
        } else if (fromHashCode > toHashCode) {
            synchronized (to) {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (from) {
                    if (from.balance - amount < 0) {
                        System.err.println("余额不足！");
                    }
                    from.balance -= amount;
                    to.balance += amount;
                    System.out.println("转账完成！");
                }
            }
        } else {
            synchronized (LOCK){
                synchronized (to) {
                    synchronized (from) {
                        if (from.balance - amount < 0) {
                            System.err.println("余额不足！");
                        }
                        from.balance -= amount;
                        to.balance += amount;
                        System.out.println("转账完成！");
                    }
                }
            }
        }
    }

    static class ChangingOrderAccount {

        private int balance;

        public ChangingOrderAccount(int balance) {
            this.balance = balance;
        }
    }


    public static void main(String[] args) throws InterruptedException {
        ChangingOrderToSolveDeadlock r1 = new ChangingOrderToSolveDeadlock();
        ChangingOrderToSolveDeadlock r2 = new ChangingOrderToSolveDeadlock();

        r1.flag = 1;
        r2.flag = 0;

        Thread thread1 = new Thread(r1);
        Thread thread2 = new Thread(r2);

        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();
        System.out.println("账户a余额：" + a.balance);
        System.out.println("账户b余额：" + b.balance);
    }
}
